package com.bookmanager.www.common.realm;

import com.bookmanager.www.common.utils.JwtToken;
import com.bookmanager.www.common.utils.JwtUtil;
import com.bookmanager.www.common.utils.JwtUtils;
import com.bookmanager.www.entity.FlBook;
import com.bookmanager.www.entity.FlUser;
import com.bookmanager.www.mapper.FlPermissionsMapper;
import com.bookmanager.www.mapper.FlRoleMapper;
import com.bookmanager.www.mapper.FlUserMapper;
import com.bookmanager.www.service.FlUserService;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * Created with IntelliJ IDEA.
 *
 * @author: 风离
 * @Date: 2021/09/19/9:43
 * @Description:
 */
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

@Slf4j
public class UserRealm extends AuthorizingRealm {

    @Resource
    FlUserMapper flUserMapper;

    @Resource
    FlUserService flUserService;

    @Resource
    FlRoleMapper flRoleMapper;

    @Resource
    FlPermissionsMapper flPermissionsMapper;
    /**
     * 多重写一个support
     * 标识这个Realm是专门用来验证JwtToken
     * 不负责验证其他的token（UsernamePasswordToken）
     * */
    @Override
    public boolean supports(AuthenticationToken token) {
        //这个token就是从过滤器中传入的jwtToken
        return token instanceof JwtToken;
    }

    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {


        System.err.println("获取主身份信息===>"+principals.getPrimaryPrincipal());
        //这里获取到的RealmName 就是下面设置的RealmName
        System.err.println("principals.getRealmNames()====>"+principals.getRealmNames());
        //判断 这里也需要和Controller层中的加密算法和 秘钥保持一致
        JwtUtil jwtUtil = new JwtUtil("userId", SignatureAlgorithm.HS256);
        System.out.println("————权限认证————");
        String userId = (String)jwtUtil.decode(principals.toString()).get("userId");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得该用户角色   默认用户角色 唯一
//        String role = flUserService.selectRoleById(userId);
        String role = flRoleMapper.selectRoleNameByUserId(userId);

        //根据角色名获取角色id
        int roleId = flRoleMapper.selectRoleIdByRoleName(role);
        log.warn("用户角色为========="+role);
        //每个角色拥有默认的权限
//        String rolePermission = userService.getRolePermission(username);
//        //每个用户可以设置新的权限
//        String permission = userService.getPermission(username);
        Set<String> roleSet = new HashSet<>();
        Set<String> permissionSet = new HashSet<>();
        permissionSet = flPermissionsMapper.selectPermissionsByRoleId(roleId);
        log.warn("当前角色所拥有的权限为========="+permissionSet);
        //需要将 role, permission 封装到 Set 作为 info.setRoles(), info.setStringPermissions() 的参数
        roleSet.add(role);
//        permissionSet.add(rolePermission);
//        permissionSet.add(permission);
        //设置该用户拥有的角色和权限
        info.setRoles(roleSet);
        info.setStringPermissions(permissionSet);
        return info;

    }


    /**
     * 认证
     * 这个token就是从过滤器中传入的jwtToken
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        String jwt = (String) token.getPrincipal();
        if (jwt == null) {
            throw new NullPointerException("jwtToken 不允许为空");
        }
        //判断 这里也需要和Controller层中的加密算法和 秘钥保持一致
        JwtUtil jwtUtil = new JwtUtil("userId", SignatureAlgorithm.HS256);
        if (!jwtUtil.isVerify(jwt)) {
            throw new UnknownAccountException("Jwt未通过校验规则");
        }
        //下面是验证这个user是否是真实存在的
        //判断数据库中userId是否存在
        String userId = (String) jwtUtil.decode(jwt).get("userId");
        System.err.println("从Token中获取到的UserId为"+userId);
        FlUser flUser = flUserMapper.selectUserById(userId);
        if (flUser == null) {
            throw new UnknownAccountException("找不到该用户信息");
        }
        log.info("在使用token登录"+userId);
        return new SimpleAuthenticationInfo(jwt,jwt,"JwtRealm");
        //这里返回的是类似账号密码的东西，但是jwtToken都是jwt字符串。还需要一个该Realm的类名

    }

}
